package com.http;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Http请求工具类(支持Https)
 * 
 * @author try
 * @version 2.2
 */
public class HttpUtil {
	private static final Logger logger = LoggerFactory.getLogger(HttpUtil.class);
	
	public static final String default_proxy_host;
	public static final Integer default_proxy_port;
	public static final boolean default_proxy_Flag;
	
	static{
		Properties properties = new Properties();
		
		InputStream in = null;
		try{
			in = Thread.currentThread().getContextClassLoader().getResourceAsStream("commons.properties");
			properties.load(in);
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			
			if(in!=null)
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			
		}
		
		default_proxy_host = properties.getProperty("httpProxyHost").trim();
		default_proxy_port = Integer.valueOf(properties.getProperty("httpProxyPort").trim());
		default_proxy_Flag = Boolean.valueOf(properties.getProperty("httpProxyFlag").trim());
	}
	
	/**连接超时时间*/
	public static int connectTimeOut = 15000; 
	
	/**读取超时时间*/
	public static int readTimeOut = 15000;
	
	/**默认读取响应体使用:UTF-8编码*/
	public static String charSet = "UTF-8";
	
	/**
	 *	获取请求输入流和流字节大小。 (失败返回NULL)
	 */
	public static Map<String,Object> getInputStreamAndLength(String requesturl,boolean proxyFlag,String proxy_Host,Integer proxy_Port){
		
		Map<String,Object> result_map = new HashMap<String,Object>();
		
		HttpURLConnection connection = null;
		InputStream in  = null;
		
		try{
			URL url = new URL(requesturl);
			if(proxyFlag){
				Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxy_Host, proxy_Port));  
				connection = (HttpURLConnection) url.openConnection(proxy);
			}else{
				connection = (HttpURLConnection) url.openConnection();
			}
			
			connection.setConnectTimeout(HttpUtil.connectTimeOut);
			connection.setReadTimeout(HttpUtil.readTimeOut);
			connection.connect();
			
			long length = connection.getContentLengthLong();
			in = connection.getInputStream();
			
			result_map.put("inputStream",in);
			result_map.put("length", length);
			
			return result_map;
		}catch(Exception e){
			logger.error("error_{}_访问异常",requesturl,e);
			return null;
		}
	}
	
	/**
	 * HTTP请求(支持Https)
	 * @param requestUrl
	 * 			请求路径
	 * @param requestMethod
	 * 			请求方式:GET  POST
	 * @param data
	 * 			POST请求数据(中文需要URL编码),GET传递NULL
	 * @return
	 * 			服务器返回信息
	 */
	public static String httpReuqest(String requestUrl,String requestMethod,String data,String charSet,boolean proxyFlag,String proxy_Host,Integer proxy_Port){
		
		StringBuffer sb = new StringBuffer();//用来装载返回数据
		
		String resultLine = null;//读取到的返回数据的每行数据。
		
		String userAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36";// 模拟浏览器
		
		String lineSeparator = System.getProperty("line.separator", "\r\n");//换行符号。
		
		OutputStream out = null;
		HttpURLConnection connection = null;
		BufferedReader reader = null;
		
		try{
			URL url = new URL(requestUrl);
			
			/**
			 * 根据访问requestUrl,打开连接,requestUrl.openConnection()函数会根据URL的类型,
			 * 返回不同的URLConnection子类的对象,这里requestUrl是一个http请求,因此实际返回的是HttpURLConnection。
			 */
			if(proxyFlag){
				//开启代理。
				Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxy_Host,proxy_Port));
				connection = (HttpURLConnection) url.openConnection(proxy);
			}else{
				connection = (HttpURLConnection) url.openConnection();
			}
			
			connection.setRequestMethod(requestMethod);//请求方式(GET,POST)
			
			connection.setConnectTimeout(HttpUtil.connectTimeOut);//连接超时
			
			connection.setReadTimeout(HttpUtil.readTimeOut);//读取超时
			
			connection.setRequestProperty("User-agent", userAgent);//请求客户端信息
			
			connection.setRequestProperty("Connection","keep-alive");//请求连接方式(连接一会)
			
			connection.setRequestProperty("Accept","*/*");//返回接收类型
			
			connection.setRequestProperty("Content-Type","application/x-www-form-urlencoded");//提交信息将url编码
			
			//post请求特有的
			connection.setDoOutput(true);//允许输出流
			
			connection.setDoInput(true); // 允许输入流
			
			connection.setUseCaches(false);//禁用缓存
			
			connection.setInstanceFollowRedirects(true);  //允许重定向
			
			if(null != data)
				connection.setFixedLengthStreamingMode(data.getBytes().length);//输出的字节数
			
			//获取请求头
			System.out.println("请求头:");
			
			Map<String, List<String>> requestmap = connection.getRequestProperties();
			Set<String> requestkeySet = requestmap.keySet();
			for(String key:requestkeySet){
				List<String> list = requestmap.get(key);
				System.out.print(key+"==>");
				for(String value :list){
					System.out.print(value+",");
				}
				System.out.println();
			}
			System.out.println();
			
			//进行连接,但是实际上要在下一句的connection.getInputStream()函数中才会真正发到 服务器。
			connection.connect();
			
			if(null !=data){
				 out = connection.getOutputStream();
				 
	             //将POST 数据写入输出流中
                 out.write(data.getBytes("UTF-8"));
			}
			
			//获取响应头
			System.out.println("响应头:");
			
			Map<String, List<String>> map = connection.getHeaderFields();
			Set<String> keySet = map.keySet();
			for(String key:keySet){
				List<String> list = map.get(key);
				System.out.print(key+"==>");
				for(String value :list){
					System.out.print(value+",");
				}
				System.out.println();
			}
			System.out.println();
			
			int code = connection.getResponseCode();
			if(code==200){
				// 读取数据编码处理
				reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), charSet));
				while ((resultLine = reader.readLine()) != null) {
					sb.append(resultLine);
					sb.append(lineSeparator);
				}
			}else{
				reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), charSet));
				while ((resultLine = reader.readLine()) != null) {
					sb.append(resultLine);
					sb.append(lineSeparator);
				}
				logger.error("error_{}_{}_{}",code,sb.toString().trim(),requestUrl);
				return "error_"+code+"_"+sb.toString().trim()+"_"+requestUrl;
			}
			
		}catch(Exception e){
			logger.error("error_{}_访问异常",requestUrl,e);
			return "error_"+requestUrl+"_访问异常==>"+e.getMessage();
		}finally {
			
			if(reader!=null){
				try {
					reader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			
			if(out!=null){
				try {
					out.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			
			if(connection!=null){
				connection.disconnect();
			}
		}
		
		return sb.toString().trim();
	}
}
